﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.WindowsAzure.StorageClient;
using Microsoft.WindowsAzure;
using System.Data.Services.Client;
using LCA.Community.DAL.Interfaces;
using LCA.Community.DAL.Model;

namespace LCA.Community.Cloud.Services
{
    /// <summary>
    /// This class is the service context for an Azure Storage Table.
    /// </summary>
    /// <typeparam name="T">The class that represents the table data.</typeparam>
    public class DataServiceContext<T> : IDataServiceContext<T> where T : BasicDataModel
    {
        private TableServiceContext _context;

        /// <summary>
        /// Initializes a new instance of the <see cref="DataServiceContext&lt;T&gt;"/> class.
        /// </summary>
        /// <param name="baseAddress">The base address.</param>
        /// <param name="credentials">The credentials.</param>
        /// <param name="tableName">Name of the table.</param>
        public DataServiceContext()
        {
            var storageAccount = CloudStorageAccount.DevelopmentStorageAccount;
            _context = new TableServiceContext(storageAccount.TableEndpoint.ToString(), storageAccount.Credentials);
            TableName = typeof(T).Name;

            storageAccount.CreateCloudTableClient().CreateTableIfNotExist(TableName);
        }

        /// <summary>
        /// Tries to attach an entity to the context.
        /// </summary>
        /// <param name="entity">The entity.</param>
        public void TryAttachTo(T entity)
        {
            try
            {
                _context.AttachTo(TableName, entity, "*");
            }
            catch (InvalidOperationException) { }
        }

        /// <summary>
        /// Adds the object.
        /// </summary>
        /// <param name="entitySetName">Name of the entity set.</param>
        /// <param name="entity">The entity.</param>
        public void AddObject(string entitySetName, object entity)
        {
            _context.AddObject(entitySetName, entity);
        }

        /// <summary>
        /// Deletes the object.
        /// </summary>
        /// <param name="entity">The entity.</param>
        public void DeleteObject(object entity)
        {
            _context.DeleteObject(entity);
        }

        /// <summary>
        /// Updates the object.
        /// </summary>
        /// <param name="entity">The entity.</param>
        public void UpdateObject(object entity)
        {
            _context.UpdateObject(entity);
        }

        /// <summary>
        /// Saves the changes.
        /// </summary>
        /// <returns>The service response</returns>
        public DataServiceResponse SaveChanges()
        {
            return _context.SaveChanges();
        }

        /// <summary>
        /// Gets the table entities.
        /// </summary>
        /// <value>The table entities.</value>
        public IQueryable<T> TableEntities
        {
            get
            {
                return _context.CreateQuery<T>(TableName);
            }
        }

        /// <summary>
        /// Gets or sets the name of the table.
        /// </summary>
        /// <value>The name of the table.</value>
        public string TableName { get; private set; }
    }
}
